package study.alex.resumedb.gae.backend;

import com.google.appengine.api.LifecycleManager;
import study.alex.resumedb.gae.EMF;
import study.alex.resumedb.gae.model.*;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

/**
 * Created with IntelliJ IDEA.
 * Author: Alexey Kuznetsov
 * Date: 15.03.14
 * Time: 13:28
 * SVN $Id$
 */
public class DefaultBackendWorker implements BackendWorker {
    private final static Logger log = Logger.getLogger(DefaultBackendWorker.class.getName());

    @Override
    public void handleRequest(HttpServletRequest request) {
        log.info("New request: " + request.getRequestURI() + ", Query: " + request.getQueryString());
        String command = request.getRequestURI();
        if (command.contains("TODO")) handleTODO(request);
        else log.warning("Method for query not implemented");
    }

    private void handleTODO(HttpServletRequest request) {
        String userId = request.getParameter("userId");
        if (userId != null && !userId.isEmpty()) {
            try {
                userId = URLDecoder.decode(userId, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                log.warning("Can't decode query parameter.  UTF-8 not supported");
                return;
            }
            updateTodoListForUser(userId);
        } else updateTodoListForAll();
    }

    private void updateTodoListForUser(String userId) {
        log.fine("Update TODO List for user " + userId);
        if (userId == null || userId.isEmpty()) return;

        EntityManager em = EMF.getEntityManager();

        EntityTransaction transaction = em.getTransaction();
        transaction.begin();
        try {
            TodoList todoList;
            Query q = em.createQuery(String.format("SELECT t FROM %s t WHERE t.userId = '%s'", TodoList.class.getName(), userId), TodoList.class);
            List<TodoList> result = q.getResultList();
            if (result == null || result.isEmpty()) {
                todoList = new TodoList(userId);
                em.persist(todoList);
            } else {
                todoList = result.get(0);
                todoList.clear();
                em.merge(todoList);
            }

            List<resumeTracker> trackers = getAllHistoryForUser(userId, em);
            if (trackers != null && trackers.size() > 0) {
                log.info("Got trackers for userId=" + userId + " size=" + trackers.size());
                for (Iterator<resumeTracker> trackerIterator = trackers.iterator(); trackerIterator.hasNext(); ) {
                    resumeTracker tracker = trackerIterator.next();
                    if (tracker.getStatus() != resumeStatus.REJECTED) {
                        Event event = new Event(userId,
                                                tracker,
                                                todoList);
                        em.persist(event);
                        log.fine("New event id=" + event.getId() + " Date: " + event.getDate());
                    }
                }
                em.merge(todoList);
                log.info("TODO List id=" + todoList.getId());
                log.info("TODO List actual size=" + todoList.getActual().size());
                log.info("TODO List late size=" + todoList.getEvents().size());
                log.info("TODO List soon size=" + todoList.getSoon().size());
            }

            transaction.commit();
        } finally {
            if (transaction.isActive()) {
                transaction.rollback();
                log.severe("Rollback in transaction");
            }
        }
        em.close();
    }

    private List<resumeTracker> getAllHistoryForUser(String userId, EntityManager em) {
        Query q = em.createQuery("SELECT t FROM " + resumeTracker.class.getName() + " t");
        List<resumeTracker> result = q.getResultList();
        return result;
    }

    private Contact getContactById(String id, EntityManager em) {
        if (id == null || id.isEmpty()) return null;
        Contact ct = em.find(Contact.class, id);

        log.fine("Got Contact info: " + ct);
        return ct;
    }

    private void updateTodoListForAll() {
        List<String> users = getUsersList();
        for (Iterator<String> iterator = users.iterator(); iterator.hasNext(); ) {
            if (!LifecycleManager.getInstance().isShuttingDown()) {
                String userId = iterator.next();
                updateTodoListForUser(userId);
            } else {
                log.info("Break update TODO lists");
                break;
            }
        }
    }

    private List<String> getUsersList() {
        EntityManager em = EMF.getEntityManager();
        List<String> users = new ArrayList<String>();
        try {
            Query q = em.createQuery("SELECT m FROM " + Mine.class.getName() + " m");
            List<Mine> result = q.getResultList();
            for (Iterator<Mine> iterator = result.iterator(); iterator.hasNext(); ) {
                Mine mine = iterator.next();
                users.add(mine.getUserId());
            }
        } finally {
            em.close();
        }
        return users;
    }

    @Override
    public void shutdown() {
        log.info("Shutdown worker");
        LifecycleManager.getInstance().interruptAllRequests();
    }
}
